#ifndef BALLER_HPP_
#define BALLER_HPP_
#include<memory>
#include<map>
#include<string>
#include <inttypes.h>

#include"base/Timestamp.hpp"
#include"net/TcpConnector.hpp"

#include"peony/proto/MsgPacket.pb.h"
#include"proto/MsgBattle.pb.h"
#include"proto/MsgLogin.pb.h"
//向前申明
class BallerMgr;
class TcpConnector;

using ConnWPtr = std::weak_ptr<TcpConnector>;
using BallerID = uint64_t;
class Baller
{
private:
	ConnWPtr					_conn;//连接的弱引用
    ProtoMsg::Dto_Baller		_ballState;//需要同步的状态
    ProtoMsg::UserInfo      	_userInfo;//玩家基础信息
    ProtoMsg::BallerOperation 	_currOperation;//玩家操作记录
protected:
	Baller(TcpConnectorPtr connPtr,BallerID id,std::string name,ProtoMsg::Color color);
	
	//检查边界
	void checkBorder();
	//根据方向,速度计算出新的位置
	void calcPosition(const ProtoMsg::BallerMove& move,int64_t ms);
	//能否吃到食物
	bool canEat(float foodx,float foody);
	//吃食物
	void eatFood(const ProtoMsg::BallerEat& eat);
	void addWeight(float kg);
  public:
	~Baller();

	BallerID		    ID(){return _userInfo.userid();}
	const std::string&	Name(){return _userInfo.username();}
	int64_t			    RoomID(){return _userInfo.roomid();}
	bool			    IsJoinArenaRoom(){return _userInfo.roomid() != -1;}
	void			    SetArenaRoom(int64_t roomID){ _userInfo.set_roomid(roomID);}
    //当玩家加入房间或重生时候,随机初始玩家位置
	void 				InitBallerState();
	//当前一局结束 清空所有状态
	void 				ResetBallerState();
	//处理玩家发送的操作,计算出玩家新的状态
	void                HandleOperation(int64_t ms);
	//保存玩家,等到帧同步时候处理
    void                SaveOperation(const ProtoMsg::BallerOperation& operation);
	void                fillBallInfo(ProtoMsg::Dto_Baller*);
	void                fillUserInfo(ProtoMsg::UserInfo*);
	
	template<class T>
	void			    SendMessage(const T& msg,int32_t code)
	{
		ProtoMsg::Packet packet;
		packet.set_name(T::descriptor()->full_name());
		packet.set_content(msg.SerializeAsString());
		packet.set_seq(0);
		packet.set_timestamp(Timestamp::Nowms());
		packet.set_code(code);
		SendPacket(packet);
	}
	void			    SendPacket(const ProtoMsg::Packet&);
	friend class BallerMgr;
};
//using BallerPtr = std::shared_ptr<Baller>;

class BallerMgr
{
private:
	std::map<BallerID,Baller*>  BallerDict;
protected:
	static uint64_t		BallerIDIndex;
	static BallerMgr*	Instance;
	BallerMgr(){}
	~BallerMgr(){}
public:
	static BallerMgr&		GetInstance();
	Baller*				    CreateBaller(TcpConnectorPtr connPtr,std::string name,ProtoMsg::Color color);

    Baller*				    QueryBaller(BallerID id);

	void					RemoveBaller(BallerID id);
	void                    RemoveBaller(Baller* baller);

    bool                    ExistBaller(BallerID id);
};
#endif
